package Logic;

import Core.Log4j2;
import Core.LogicFramework;
import microgame.airplane.proto.Game;
import microgame.airplane.proto.MsgTypeOuterClass;
import microgame.toolset.datatable.DataTable;
import microgame.toolset.datatable.DataTableManager;
import microgame.toolset.datatable.Row;
import za.co.luma.geom.Vector2DDouble;

import java.util.ArrayList;
import java.util.LinkedList;

public class PropStubGroup {
    private ArrayList<PropStub> propStubList = new ArrayList<PropStub>();
    private float generateTimeInterval;
    private Match match;
    private int templateId;
    private float timeAccumulationSinceLastTimeGen;
    private int maxLimit;
    private float chance;
    private Row row;

    public PropStubGroup(int templateId, Match match) {
        DataTable table = DataTableManager.Instance().GetDataTable("prop");
        row = table.GetRow(templateId);
        generateTimeInterval = row.GetFloat("appeartime");
        maxLimit = row.GetInteger("maxcount");
        chance = row.GetFloat("chance");
        timeAccumulationSinceLastTimeGen = 0;
        this.match = match;
        this.templateId = templateId;
    }

    public void Add(PropStub propStub) {
        propStubList.add(propStub);
    }

    public void Remove(PropStub propStub) {
        propStubList.remove(propStub);
    }

    //参数的单位是秒
    public void Tick(float frameTime) {
        timeAccumulationSinceLastTimeGen += frameTime;
        if (timeAccumulationSinceLastTimeGen > generateTimeInterval) {
            if (propStubList.size() < maxLimit && Util.GetRandomFloat() > chance) {
                GenPropStub();
            }
            timeAccumulationSinceLastTimeGen = 0;
        }

        for (int i = 0; i < propStubList.size(); ++i) {
            PropStub propStub = propStubList.get(i);
            propStub.Update(frameTime);

            TryRemovePropStub(propStub);
        }
    }

    //@ clientid, 是sAirPlaneSpawnPush推送给客户端时分配的短ID
    public void PropStubCollision(int playerId, int propStubId) {
        boolean exist = false;
        int index = -1;
        for (int i = 0; i < propStubList.size(); ++i) {
            if (propStubList.get(i).id == propStubId) {
                exist = true;
                index = i;
            }
        }

        if (exist) {
            PropStub propStub = propStubList.get(index);
            propStub.valid = false;

            //发送道具stub撞击的消息，发送req的客户端一样需要这个消息再做撞击反馈给用户
            Game.sPropStubCollisionPush.Builder scbuilder = Game.sPropStubCollisionPush.newBuilder();
            scbuilder.setPlayerid(playerId);
            scbuilder.setTemplateid(propStub.templateId);
            scbuilder.setId(propStub.id);
            Game.sPropStubCollisionPush scpush = scbuilder.build();
            match.SendMessageToAllClients(MsgTypeOuterClass.MsgType.sPropStubCollisionPush.getNumber(), scpush.toByteArray());

            //这里在服务器中删除该prop stub，并且给客户端发送移除消息（客户端可选择在上面的消息中一并做移除，那么可以忽略该消息）
            TryRemovePropStub(propStubId);
        }
    }

    private void TryRemovePropStub(int id) {
        for (int i = 0; i < propStubList.size(); ++i) {
            if (propStubList.get(i).id == id) {
                TryRemovePropStub(propStubList.get(i));
                Log4j2.LOGGER.warn("消除道具， id = "  + id);
            }
        }
    }

    private void TryRemovePropStub(PropStub propStub) {
        if (!propStub.valid) {
            propStubList.remove(propStub);

            Game.sPropStubRemovePush.Builder builder = Game.sPropStubRemovePush.newBuilder();
            builder.setTemplateid(propStub.templateId);
            builder.setId(propStub.id);
            Game.sPropStubRemovePush push = builder.build();
            match.SendMessageToAllClients(MsgTypeOuterClass.MsgType.sPropStubRemovePush.getNumber(), push.toByteArray());
        }
    }

    private void GenPropStub() {
        String name = row.GetString("name");
        int type = row.GetInteger("type");
        int value = row.GetInteger("value");
        float life = row.GetFloat("life");

        PropStub propStub = new PropStub(templateId, match.GetPropStubManager().NextPropId(), name, type, value, life);
        propStubList.add(propStub);

        Game.sPropStubSpawnPush.Builder builder = Game.sPropStubSpawnPush.newBuilder();
        builder.setId(propStub.id);
        builder.setTemplateid(templateId);

        Point2d point = GetPropSpawnPoint();
        propStub.SetTransform(point.x, point.y, 0);
        builder.setX(point.x);
        builder.setY(point.y);
        builder.setAngle(0);

        Game.sPropStubSpawnPush push = builder.build();
        match.SendMessageToAllClients(MsgTypeOuterClass.MsgType.sPropStubSpawnPush.getNumber(), push.toByteArray());
    }

    private Point2d GetPropSpawnPoint() {
        LinkedList<Vector2DDouble> points = match.GetPropSpawnPoints();
        Vector2DDouble vector = points.pop();

        Point2d point = new Point2d(((int)vector.x), ((int)vector.y));
        points.offerLast(vector);
        return point;
    }
}
